package com.coinworld.utils;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.coinworld.constants.CONSTANTS;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.apache.commons.beanutils.BeanUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description
 * @author:
 * @create: 2019-08-30 14:46
 **/
@Component
public class PubTools {

    /**
     * 属性复制
     *
     * @description
     * @author
     * @date 2019/8/30
     */
    public static <T> T copyEncryptProperties(String encrypt, Class<T> clazz) {
        return JSONObject.toJavaObject(JSONObject.parseObject(AESUtils.decrypt(encrypt)), clazz);
    }

    public static boolean checkXSSAndSql(String value) {
        boolean flag = false;
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and
            // uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
            // Avoid null characters
            /** value = value.replaceAll("", ""); ***/
            // Avoid anything between script tags
            Pattern scriptPattern = Pattern.compile(
                    "<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Avoid anything in a
            // src="http://www.yihaomen.com/article/java/..." type of
            // e-xpression
            scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Remove any lonesome </script> tag
            scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Remove any lonesome <script ...> tag
            scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Avoid eval(...) expressions
            scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Avoid e-xpression(...) expressions
            scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Avoid javascript:... expressions
            scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Avoid vbscript:... expressions
            scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
            // Avoid onload= expressions
            scriptPattern = Pattern.compile("onload(.*?)=",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            flag = scriptPattern.matcher(value).find();
            if (flag) {
                return flag;
            }
        }
        return flag;
    }

    /**
     * 属性复制
     *
     * @description
     * @author
     * @date 2019/8/30
     */
    public static <T> T copyProperties(JSONObject object, Class<T> clazz) {
        return JSONObject.toJavaObject(object, clazz);
    }

    //USDT金额验证
    public static boolean isUSDTNumber(String str) {
        Pattern pattern = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,8})?$"); // 判断小数点后8位的数字的正则表达式
        Matcher match = pattern.matcher(str);
        return match.matches();
    }


    /**
     * 验证正整数
     *
     * @param str
     * @return
     */
    public static boolean isPureDigital(String str) {
        if (str == null || "".equals(str)) {
            return false;
        }

        Pattern p;
        Matcher m;
        p = Pattern.compile("[0-9]*");
        m = p.matcher(str);
        if (m.matches()) {
            return true;
        } else {
            return false;
        }
    }


    public static String documentBody(String httpHost, String url) {
        Element doc = Jsoup.parseBodyFragment(url).body();
        Elements pngs = doc.select("img[src]");
        for (Element element : pngs) {
            String imgUrl = element.attr("src");
            // 会去匹配我们富文本的图片的 src 的相对路径的首个字符，请注意一下
            if (imgUrl.trim().startsWith("/")) {
                imgUrl = httpHost + imgUrl;
                element.attr("src", imgUrl);
            }
        }
        return url = doc.toString();
    }

    public static String removeDocumentDomain(String url) {
        Element doc = Jsoup.parseBodyFragment(url).body();
        Elements pngs = doc.select("img[src]");
        for (Element element : pngs) {
            String imgUrl = element.attr("src");
            if (imgUrl.trim().startsWith("http")) {
                element.attr("src", imgUrl.replaceAll(CONSTANTS.OSS_CND_FILE_URI, ""));
            }
        }
        return url = doc.toString();
    }


    public static BigDecimal usdtToCnyPrice() {
        String mes = HttpUtil.requestByGet(CONSTANTS.HUO_BI_EXCHANGE_RATE_URL, null);
        JSONObject result = JSONObject.parseObject(mes);
        //默认值
        BigDecimal rate = new BigDecimal("7.05");
        if (result.getInteger("code") == 200) {
            JSONArray data = result.getJSONArray("data");
            for (int i = 0; i < data.size(); i++) {
                if (data.getJSONObject(i).getString("name").equals(CONSTANTS.USDT_CNY_RATE)) {
                    rate = new BigDecimal(data.getJSONObject(i).getString("rate"));
                    break;
                }
            }
        }
        return rate;
    }

    /**
     * 检查usdt与fmt兑换是否开盘
     *
     * @return
     */
    public static boolean checkTranIsOpen() {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");//设置日期格式
        //初始化
        Date nowTime = null;
        Date beginTime = null;
        Date endTime = null;
        try {
            //格式化当前时间格式
            nowTime = df.parse(df.format(new Date()));
            //定义开始时间
            beginTime = df.parse(CONSTANTS.START_TRANSACTION_TIME);
            //定义结束时间
            endTime = df.parse(CONSTANTS.END_TRANSACTION_TIME);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //调用判断方法
        return DateUtils.belongCalendar(nowTime, beginTime, endTime);
    }

    public static boolean checkTranIsClose() {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");//设置日期格式
        //初始化
        Date nowTime = null;
        Date beginTime = null;
        Date endTime = null;
        try {
            //格式化当前时间格式
            nowTime = df.parse(df.format(new Date()));
            //定义开始时间
            beginTime = df.parse(CONSTANTS.START_TRANSACTION_TIME);
            //定义结束时间
            endTime = df.parse(CONSTANTS.END_UN_LOCK_TRANSACTION_TIME);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //调用判断方法
        return DateUtils.belongCalendar(nowTime, beginTime, endTime);
    }


    /**
     * TODO 临时的实名认证维护时间
     *
     * @return
     */
    public static boolean checkRealIsOpen() {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");//设置日期格式
        //初始化
        Date nowTime = null;
        Date beginTime = null;
        Date endTime = null;
        try {
            //格式化当前时间格式
            nowTime = df.parse(df.format(new Date()));
            //定义开始时间
            beginTime = df.parse("20:00");
            //定义结束时间
            endTime = df.parse("22:15");
        } catch (Exception e) {
            e.printStackTrace();
        }
        //调用判断方法
        return DateUtils.belongCalendar(nowTime, beginTime, endTime);
    }

    /**
     * 隐藏身份证号中间位数
     *
     * @param IdCard
     * @return
     */
    public static String hiddenIdCard(String IdCard) {
        return IdCard.replaceAll("(\\d{3})\\d{12}(\\w{3})", "$1*****$2");
    }

    /**
     * 隐藏手机号中间几位
     *
     * @param mobile
     * @return
     */
    public static String hiddenMolbie(String mobile) {
        return mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }

    // 姓名隐藏
    public static String replaceName(String str) {
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        if (str.length() == 1) {
            return str;
        }
        //姓名首部
        String surName = str.substring(0, 1);
        //姓名尾部
        String tailName = str.substring(str.length() - 1);
        if (str.length() == 2) {
            return surName + "*";
        } else {
            int i = str.length() - 2;
            String s = "";
            for (int j = 0; j < i; j++) {
                s = s + "*";
            }
            return surName + s + tailName;
        }
    }

    public static Map<String, String> convertToMap(Object obj) {
        try {
            if (obj instanceof Map) {
                return (Map)obj;
            }
            Map<String, String> returnMap = BeanUtils.describe(obj);
            returnMap.remove("class");
            return returnMap;
        } catch (IllegalAccessException e1) {
            e1.getMessage();
        } catch (InvocationTargetException e2) {
            e2.getMessage();
        } catch (NoSuchMethodException e3) {
            e3.getMessage();
        }
        return new HashMap();
    }

    public static <T> T strToBean(String str, Class<T> clazz){
        return (T) net.sf.json.JSONObject.toBean(net.sf.json.JSONObject.fromObject(str), clazz);
    }


    public static String getPinYin(String str) throws BadHanyuPinyinOutputFormatCombination {
        char[] t1=null;
        t1=str.toCharArray();
        String[] t2=new String[t1.length];
        HanyuPinyinOutputFormat t3=new HanyuPinyinOutputFormat();
        t3.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        t3.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        t3.setVCharType(HanyuPinyinVCharType.WITH_V);
        String t4="";
        for(int i=0;i<t1.length;i++) {
            if(java.lang.Character.toString(t1[i]).matches("[\\u4E00-\\u9FA5]+")) {}
            t2= PinyinHelper.toHanyuPinyinStringArray(t1[i], t3);
            t4+=t2[0];
        }
        return t4;
    }

    public static String getHeadPinYin(String chineseLan) {
        String ret = "";
        // 将汉字转换为字符数组
        char[] charChineseLan = chineseLan.toCharArray();
        // 定义输出格式
        HanyuPinyinOutputFormat hpFormat = new HanyuPinyinOutputFormat();
        // 小写格式输出
        hpFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 不需要语调输出
        hpFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        try {
            for (int i = 0; i < charChineseLan.length; i++) {
                if(String.valueOf(charChineseLan[i]).matches("[\u4e00-\u9fa5]+")) {
                    // 如果字符是中文,则将中文转为汉语拼音（获取全拼则去掉红色的代码即可）
                    ret += PinyinHelper.toHanyuPinyinStringArray(charChineseLan[i], hpFormat)[0].substring(0, 1);
                } else {
                    // 如果字符不是中文,则不转换
                    ret += charChineseLan[i];
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * 判断是否为数字
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        return pattern.matcher(str).matches();
    }



    /**
     * // 判断小数点后2位的数字的正则表达式
     * @param str
     * @return
     */
    public static boolean isNumberTwoDecimal(String str){
        Pattern pattern2=Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){2})?$");
        Matcher match2=pattern2.matcher(str);
        Pattern pattern1=Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){1})?$");
        Matcher match1=pattern1.matcher(str);
        return match2.matches() || match1.matches();
    }



     /*
    校验过程：
    1、从卡号最后一位数字开始，逆向将奇数位(1、3、5等等)相加。
    2、从卡号最后一位数字开始，逆向将偶数位数字，先乘以2（如果乘积为两位数，将个位十位数字相加，即将其减去9），再求和。
    3、将奇数位总和加上偶数位总和，结果应该可以被10整除。
    */
    /**
     * 校验银行卡卡号
     */
    public static boolean checkBankCard(String bankCard) {
        if(bankCard.length() < 15 || bankCard.length() > 19) {
            return false;
        }
        char bit = getBankCardCheckCode(bankCard.substring(0, bankCard.length() - 1));
        if(bit == 'N'){
            return false;
        }
        return bankCard.charAt(bankCard.length() - 1) == bit;
    }

    /**
     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
     * @param nonCheckCodeBankCard
     * @return
     */
    public static char getBankCardCheckCode(String nonCheckCodeBankCard){
        if(nonCheckCodeBankCard == null || nonCheckCodeBankCard.trim().length() == 0
                || !nonCheckCodeBankCard.matches("\\d+")) {
            //如果传的不是数据返回N
            return 'N';
        }
        char[] chs = nonCheckCodeBankCard.trim().toCharArray();
        int luhmSum = 0;
        for(int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if(j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char)((10 - luhmSum % 10) + '0');
    }


    /**
     * 获取随机字符串
     * @param length 生成的随机字符串长度
     * */
    public static String getStrRandom(int length){
        if(length<1){
            return "";
        }else{
            String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz";
            StringBuilder sb = new StringBuilder();
            Random ra = new Random();
            int index = 0;
            for (int i = 0; i < length ;i++ ) {
                index = ra.nextInt(str.length());
                sb.append(str.charAt(index));
            }
            return sb.toString();
        }
    }



    public static boolean isEmail(String string) {
        if (string == null)
            return false;
        String regEx1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
        Pattern p;
        Matcher m;
        p = Pattern.compile(regEx1);
        m = p.matcher(string);
        if (m.matches())
            return true;
        else
            return false;
    }


}
